package me.zhengjie.nettydemo.nettty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.DecoderException;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

@Slf4j
public class MultiProtocolDecoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception  {
        if (!in.isReadable()) {
            return;
        }
        // 读取第一个字节作为帧头
        byte frameHeader = in.readByte();
        log.info("解码器读取字节:{},头:{}", ByteBufUtil.hexDump(in), frameHeader);
        // 根据帧头判断协议
        if (frameHeader == (byte) 0x01) {
            if (!in.isReadable()) {
                log.error("No more readable bytes after frame header");
                return;
            }
            byte b = in.readByte();
            log.info("功能码为:{}", b);
            if (b == (byte) 0x03) {
                if (!in.isReadable()) {
                    log.error("No more readable bytes after function code");
                    return;
                }
                int currentReaderIndex = in.readerIndex();
                log.info("当前读取指针位置: {}", currentReaderIndex);
                log.info("打印数据：{}", ByteBufUtil.hexDump(in));
                byte size = in.readByte();
                String hexSize = String.format("%02X", size);
                Integer i1 = Integer.valueOf(hexSize);
                log.info("长度：{},i1:{}", size,i1);
                int remainingLength;
                int length = in.readableBytes();
                remainingLength = length - 2;
                log.info("剩余长度：{},减掉校验码长度后：{}", length, remainingLength);
                if (i1 == remainingLength) {
                    int i = in.readerIndex();
                    log.info("i索引：{}",i);
                    // 读取整个消息
                    ByteBuf byteBuf = in.readerIndex(i - 2);
                    log.info("打印buf：{}",byteBuf);
                    out.add(byteBuf.retain());
                } else {
                    log.error("Size mismatch: expected {} but got {}", size, remainingLength);
                    in.clear();
                }
            } else if (b == (byte) 0x06) {
                int length = in.readableBytes();
                if (length == 6) {
                    int i = in.readerIndex();
                    ByteBuf byteBuf = in.readerIndex(i - 1);
                    // 增加引用计数
                    out.add(byteBuf.retain());
                } else {
                    log.error("Length mismatch: expected 6 but got {}", length);
                }
            }
        } else if (frameHeader == (byte) 0xcc) {
            handleProtocolTwo(ctx, in, out);
        } else {
            // 处理未知帧头或抛出异常
            log.error("Received unknown frame header: {}", frameHeader);
        }
    }


    private void decodeProtocolOne(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, int startIdx) throws Exception {
        log.info("协议1报文:{},保存报头 'aa' 的索引位置:{}", ByteBufUtil.hexDump(in), startIdx);
        // 定位报尾 'bb' 的位置
        int endIndex = in.readerIndex() + in.readableBytes();
        int bbIndex = in.indexOf(in.readerIndex(), endIndex, (byte) 0xbb);
        log.info("定位报尾 'bb' 的位置:{},readerIndex：{}，in.readableBytes()：{},endIndex：{}", bbIndex, in.readerIndex(), in.readableBytes(), endIndex);
        int b = in.readByte();
        log.info("数据长度:{}", b);
        if (bbIndex != -1) {
            // 计算报文的实际长度（从报头到报尾）
            int lengthToRead = bbIndex - startIdx + 1;

            // 截取从报头到报尾的报文
            ByteBuf frame = in.slice(startIdx, lengthToRead);
            ByteBuf buf = Unpooled.buffer(b + 1);
            buf.writeBytes(frame);
            // 转换截取的报文为十六进制字符串
            log.info("截取的报文: {}", ByteBufUtil.hexDump(buf));
            out.add(buf);
            in.clear();
        } else {
            System.out.println("未找到报尾 'bb'");
            throw new DecoderException("Not enough data to read for protocol one");
        }

    }

    private void handleProtocolTwo(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        log.info("协议2报文:{}", ByteBufUtil.hexDump(in));
        log.info("协议2可读长度:{}", in.readableBytes());
        int size = in.readableBytes();

        if (size >= 10) {
            ByteBuf buf = Unpooled.buffer(10); // 确保缓冲区大小至少为10
            buf.writeByte(0xcc); // 写入协议2的帧头

            // 只读取并写入10个字节的数据
            for (int i = 0; i < 10; i++) {
                if (in.isReadable()) { // 检查是否还有可读字节
                    byte b = in.readByte();
                    buf.writeByte(b);
                } else {
                    // 如果没有足够的数据，抛出异常
                    throw new DecoderException("Not enough data to read for protocol two");
                }
            }

            log.info("协议2打印buf:{}", ByteBufUtil.hexDump(buf));
            // 将解码后的数据帧添加到输出列表
            out.add(buf);
            in.clear();
        } else {
            // 如果可读字节数小于10，抛出异常
            throw new DecoderException("Not enough data to read for protocol two");
        }

//        if (size !=10){
//            throw new DecoderException("Not enough data to read for protocol one");
//        }
//        ByteBuf buf = Unpooled.buffer(11);
//        buf.writeByte(0xcc);
//        for (int i = 0; i < size; i++) {
//            //功能码
//            byte b = in.readByte();
//            buf.writeByte(b);
//        }
//        log.info("协议2打印buf:{}",ByteBufUtil.hexDump(buf));
//        // 将解码后的数据帧添加到输出列表
//        out.add(buf);
    }
}
